package com.stockz.ui.swing.charting.display.indicator;

import java.awt.Graphics2D;
import java.util.List;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.stockz.core.model.Bar;
import com.stockz.core.util.BarUtil.BarValueType;
import com.stockz.core.util.ListUtil;
import com.stockz.ui.swing.charting.painter.indicator.LineIndicatorPainter;
import com.stockz.ui.swing.charting.util.UIChartingConstant.OVERLAY;

@Component
@Scope("prototype")
public class StandardDeviation extends
		AbstractDisplayableIndicatorConfiguration{

	public static class Configuration{
		private int span = 20;

		public int getSpan() {
			return span;
		}

		public void setSpan(int span) {
			this.span = span;
		}
	}
	
	public static double[] values(double[] barValues, int span){
		if(barValues != null){
			double[] values = new double[barValues.length];
			double sum = 0; 
			double sumSquared = 0;
			if(barValues.length > 0 && span > 1 && span <= barValues.length){
				for(int i = barValues.length-1; i >=0; i--){
					if(barValues[i] == 0){
						continue;
					}
					if(i > barValues.length - span){
						
					}else if(i ==  barValues.length - span){
						if(barValues[i] == 0){
							if(i == 0){
								values[i] = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)))*100/barValues[1];
							}else{
								values[i] = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)))*100/barValues[i-1];
							}
						}else{
							values[i] = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)))*100/barValues[i];
						}
					}else{
						if(barValues[i] == 0){
							if(i == 0){
								values[i] = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)))*100/barValues[1];
							}else{
								values[i] = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)))*100/barValues[i-1];
							}
						}else{
							values[i] = Math.sqrt((span * sumSquared - (sum * sum))/ (span * (span- 1)))*100/barValues[i];
						}			
						sum -= barValues[i+span];
						sumSquared -= (barValues[i+span]*barValues[i+span]);
					}
					sum += barValues[i];
					sumSquared += (barValues[i]*barValues[i]);
				}
			}
			return values;
		}
		return new double[0];
	}
	
	
	private Configuration configuration = new Configuration();
	
	@Override
	public String getFullName() {
		return "Standard Deviation";
	}

	@Override
	public String getShortName() {
		return "SD";
	}

	@Override
	public String getDescription() {
		return getFullName()+", "+configuration.getSpan();
	}

	@Override
	public OVERLAY getOverlay() {
		return OVERLAY.INDEPENDENT;
	}

	@Override
	public boolean isOverlappable() {
		return true;
	}

	@Override
	public void paint(Graphics2D g) {
		LineIndicatorPainter.paint(g, this);
	}

	@Override
	public BarValueType getBarValueType() {
		return barValueType;
	}
	
	@Override
	public void setBarValueType(BarValueType barValueType) {
		this.barValueType = barValueType;
	}

	@Override
	public Object getConfiguration() {
		return configuration;
	}

	@Override
	public void refreshValues() {
		List<Bar> barList = getStockChartPanel().getStockChartPanelState().getBarList();
		if(barList != null && barList.size() > configuration.getSpan()){
			double[] barValues = ListUtil.convert(barList, getBarValueType());
			setValues(StandardDeviation.values(barValues, configuration.getSpan()));
		}
	}

}
